import jsonpath
from utils.LogUtil import logger
from utils.YamlUtil import YamlUtil

from apiCore.RequestCore import RequestCore

class ExtractUtil:

    def __init__(self):
        self.yaml_util = YamlUtil()
        self.reqCore = RequestCore()
        # self.fk = Faker(locale="zh_CN")

    def extract_case(self, response, extract):
        """
        根据extract表达式，获取接口内容并存入yaml文件
        :param response: 响应结果
        :param extract:yaml文件中的extract表达式
        :return:
        """
        if extract:
            logger.info(f"yaml文件中获取到的extract：{extract}")
            for k, v in extract.items():
                for key, expression in v.items():
                    if k in response:
                        try:
                            value = self.extract_by_jsonpath(response, expression)
                            # 写入value
                            self.yaml_util.write_extract_yaml({key: value})
                            logger.info(f"变量{key}成功写入extract.yaml文件，值为:{value}")
                        except Exception as e:
                            logger.error(f"变量{key}写入extract.yaml文件失败，请检查，error:{e}")
                    else:
                        logger.info(f"变量{k}未在响应结果中找到")

    def extract_by_jsonpath(self, extract_value: dict, extract_expression: str):
        """
        json path 取值   用于 数据提取，从接口响应中提取值并存储（如写入 extract.yaml）
        :param extract_value: response.json()
        :param extract_expression: eg: '$.code'
        :return: None或 提取的第一个值 或全部
        """
        # 如果 extract_expression 不是字符串，直接返回原始值
        if not isinstance(extract_expression, str):
            return extract_expression

        # 使用 jsonpath 提取数据
        try:
            extracted = jsonpath.jsonpath(extract_value, extract_expression)
        except Exception as e:
            logger.error(f"JSONPath 解析失败: {e}")
            return None

        # 处理提取结果
        if extracted is False:  # 无匹配时返回False
            return None
        elif not extracted:  # 空列表
            return None
        elif len(extracted) == 1:  # 单元素列表
            return extracted[0]
        else:  # 多元素列表
            return extracted

    def extract_yaml_info(self, yaml_info):
        """
        将yaml文件中获取的数据，有模版表达式的进行替换 类似${....}
        :param yaml_info:
        :return: json格式数据

           直接处理字典数据，无需通过 JSON 字符串转换。
        """
        if isinstance(yaml_info, str):
            # 如果是字符串（如模板表达式），才进行替换
            return self.process_data(yaml_info)
        elif isinstance(yaml_info, dict):
            # 递归处理字典中的每个值
            return {k: self.extract_yaml_info(v) for k, v in yaml_info.items()}
        elif isinstance(yaml_info, list):
            # 递归处理列表中的每个元素
            return [self.extract_yaml_info(item) for item in yaml_info]
        else:
            # 其他类型（如 None、int、bool）直接返回
            return yaml_info

    # yaml文件模版替换
    # def process_data(self, data):
    #     """
    #     处理${...}模板表达式
    #     """
    #     from utils.DataProvider import DataProvider  # 动态导入避免循环依赖
    #     provider = DataProvider()
    #
    #     while "${" in data and "}" in data:
    #         start_index = data.index('${')
    #         end_index = data.index("}", start_index)
    #         func_full_name = data[start_index: end_index + 1]
    #         func_name = data[start_index + 2: data.index('(', start_index)]
    #
    #         # 提取参数
    #         params_str = data[data.index('(', start_index) + 1: end_index - 1]
    #         params = self._parse_function_params(params_str)
    #
    #         # 调用DataProvider中的方法
    #         func = getattr(provider, func_name, None)
    #         if func:
    #             result = func(*params)
    #             data = data.replace(func_full_name, str(result))
    #     return data
    def process_data(self, data):
        """
        改进版：支持嵌套${...}模板表达式
        """
        from utils.DataProvider import DataProvider
        provider = DataProvider()

        if not isinstance(data, str):
            return data

        while "${" in data and "}" in data:
            # 找到最内层的${...}
            start_pos = data.rfind("${")
            end_pos = data.find("}", start_pos)

            if start_pos == -1 or end_pos == -1:
                break

            full_expr = data[start_pos:end_pos + 1]

            # 提取函数名和参数
            func_name = full_expr[2:full_expr.find("(")]
            params_str = full_expr[full_expr.find("(") + 1:full_expr.rfind(")")]

            # 递归处理参数中的嵌套模板
            parsed_params = []
            for param in self._parse_function_params(params_str):
                if "${" in param and "}" in param:
                    parsed_params.append(self.process_data(param))
                else:
                    parsed_params.append(param.strip('"\''))

            # 调用DataProvider方法
            func = getattr(provider, func_name, None)
            if func:
                result = str(func(*parsed_params))
                data = data[:start_pos] + result + data[end_pos + 1:]

        return data

    def _parse_function_params(self, params_str):
        """解析函数参数，支持带引号的字符串"""
        params = []
        current_param = []
        in_quotes = False
        quote_char = None

        for char in params_str:
            if char in ('"', "'") and not in_quotes:
                in_quotes = True
                quote_char = char
            elif char == quote_char and in_quotes:
                in_quotes = False
                quote_char = None
            elif char == ',' and not in_quotes:
                params.append(''.join(current_param).strip())
                current_param = []
            else:
                current_param.append(char)

        if current_param:
            params.append(''.join(current_param).strip())

        # 移除参数中的引号
        params = [p.strip("'\"") for p in params]
        return params
